/**
 * This class represents the collected sensor data as a tree widget.
 */
package org.hackystat.ui.sensordataviewer.client;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;

import com.google.gwt.user.client.ui.Tree;

/**
 * This class embodies an ordered list of sensor data events as a tree widget.
 * @author David J. Nickles
 *
 */
public class EventCollection extends Tree {
  
  private static int oddoreven;
  private int count;
  private int modCount;
  private CompositeWidget master;
  private Date lastArrivalTstamp;
  private ArrayList modEventsCache;

  /**
   * Initializes a SDBEventCollection for classifying and storing SDBEvents.
   * @param list of the request response from the servlet
   * 
   * @gwt.typeArgs list <java.util.ArrayList<java.lang.String>>
   */
  private final void populate(ArrayList list) {
    /** @gwt.typeArgs myit <org.hackystat.ui.sensordataviewer.SDVEvent> */
    Iterator modit = this.modEventsCache.iterator();
    while (modit.hasNext()) {
      ((Event)modit.next()).age();
    }
    /** @gwt.typeArgs modEventsCache <org.hackystat.ui.sensordataviewer.SDVEvent> */
    this.modEventsCache = new ArrayList();
    Event lastEvent = null;
    long lastEventTstamp = 0L;
    if (this.getItemCount() > 0) {
      lastEvent = (Event)this.getItem(this.getItemCount() - 1);
      lastEventTstamp = lastEvent.getEventTstamp();
    }
    Event e = null;
    this.modCount = 0;
    /** @gwt.typeArgs it <org.hackystat.ui.sensordataviewer.SDVEvent> */
    Iterator it = list.listIterator();
    while (it.hasNext()) {
      /** @gwt.typeArgs rawEvent <java.lang.String> */
      ArrayList rawEvent = (ArrayList)it.next();
      e = new Event(rawEvent, ++this.oddoreven, this.master);
      this.modCount += e.size();
      this.count += e.size();
      // add e to modEventsCache
      if (e.getEventTstamp() > lastEventTstamp) {
        addItem(e);
        this.modEventsCache.add(e);
      }
      else if (e.getEventTstamp() == lastEventTstamp) {
        lastEvent.merge(e);
        this.modEventsCache.add(lastEvent);
      }
      else {
        Event existingEvent = null;
        boolean eventNotAdded = true;
        /** @gwt.typeArgs myit <org.hackystat.ui.sensordataviewer.SDVEvent> */
        Iterator myit = this.iterator();
        while (myit.hasNext()) {
          existingEvent = (Event)myit.next();
          if (e.getEventTstamp() == existingEvent.getEventTstamp()) {
            existingEvent.merge(e);
            this.modEventsCache.add(existingEvent);
            eventNotAdded = false;
            break;
          } 
          else if (e.getEventTstamp() < existingEvent.getEventTstamp()) {
            /** @gwt.typeArgs holdingpin <org.hackystat.ui.sensordataviewer.SDVEvent> */
            ArrayList holdingpin = new ArrayList();
            holdingpin.add(existingEvent);
            while (myit.hasNext()) {
              holdingpin.add(myit.next());
            }
            addItem(e);
            this.modEventsCache.add(e);
            /** @gwt.typeArgs myit <org.hackystat.ui.sensordataviewer.SDVEvent> */
            Iterator pinit = this.iterator();
            while (pinit.hasNext()) {
              addItem((Event)pinit.next());
            }
            eventNotAdded = false;
            break;
          }
        }
        if (eventNotAdded) {
          addItem(e);
          this.modEventsCache.add(e);
        }
      }
    }
    Date tstamp = e.getLastTstamp();
    if (tstamp.after(this.lastArrivalTstamp)) {
      this.lastArrivalTstamp = tstamp;
    }
  }

  /**
   * Creates an empty SDVEventColelction for classifying and storing SDVEvents.
   * @param widget SDBWidget that contains this tree
   */
  public EventCollection(CompositeWidget widget) {
    this.master = widget;
    this.lastArrivalTstamp = new Date(0);
    /** @gwt.typeArgs modEventsCache <org.hackystat.ui.sensordataviewer.SDVEvent> */
    this.modEventsCache = new ArrayList();
  }

  /**
   * Creates a SDBEventColelction that contsins the new list of items as SDBEvents.
   * @param list of items to put into the Tree.
   * @param widget the master composite widget that contains this widget
   * 
   * @gwt.typeArgs list <java.lang.String>
   */
  public EventCollection(CompositeWidget widget, ArrayList list) {
    this.master = widget;
    this.lastArrivalTstamp = new Date(0);
    /** @gwt.typeArgs modEventsCache <org.hackystat.ui.sensordataviewer.SDVEvent> */
    this.modEventsCache = new ArrayList();
    populate(list);
  }
  
  /**
   * This method resets the Tree to contain only the new list of items.
   * @param list of items to put into the Tree.
   * @return a Tree reset to contain only the new list of items.
   * 
   * @gwt.typeArgs list <java.lang.String>
   */
  public Tree resetSensorData(ArrayList list) {
    this.count = 0;
    this.clear();
    populate(list);
    return this;
  }

  /**
   * Adds the sensor data index items to this SDVEventCollection's list of items as SDVEvents.
   * @param list of items to put into the Tree.
   * 
   * @gwt.typeArgs list <java.lang.String>
   */
  public void addSensorData(ArrayList list) {
    populate(list);
    this.count += list.size();
  }
  
  /**
   * Gets the count of elements.
   * @return the count of elements.
   */
  public int size() {
    return this.count;
  }
  
  /**
   * Gets the count of new elements.
   * @return the count of new elements.
   */
  public int modSize() {
    return this.modCount;
  }

  /**
   * Gets the timestamp of the last item in this event.
   * @return Date object that is the last timestamp that occurs in this collection.
   */
  public Date getLastTstamp() {
    return this.lastArrivalTstamp;
  }
}